
package com.ioc;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

import com.ioc.BeanFactory;

/**
 * @author xied
 * @version 1.0
 */
public class IocFactoryDefaultImpl implements IocFactory<Object> {
	
	public Object newInstance(Class<?> cls) {
		
	   //return createObject(cls);
	   return this.createObjectByField(cls);
	}
	
	/**
	 */
	public Object newInstanceBySingel(Class<?> cls) {
		if (IocContains.isContain(cls)) {
			return IocContains.get(cls);
		}
		
		//Object obj = createObject(cls);
		Object obj = this.createObjectByField(cls);
		
		Object old = IocContains.put(cls, obj);
		if (old != null && old != obj) 
			obj = old;
	    return obj;
	
	}
	
	/**
	 * @param cls
	 * @return
	 */
	private Object createObject(Class <?> cls) {
		
		Object obj = null;
	
		try {
			obj = cls.newInstance();
    	    Method []methods = cls.getDeclaredMethods();
			for (Method m : methods) {
				BeanFactory factory = m.getAnnotation(BeanFactory.class);
				if (factory != null) {
					Object myObject = null;
					Class<?> myclass = factory.DIClass();
					if (myclass == null) continue;
			    	if (this.check(myclass))
					    myObject = createObject(myclass);
			    	else
			    		myObject = myclass.newInstance();
			    	
			    	if (myObject != null) {
						 
			    		m.invoke(obj, new Object[]{myObject});
					}
				}
			}
        } catch (Exception e) {
			System.out.println("BeanFactory �����������:"+e.getMessage());
			e.printStackTrace();
		} 
       
		return obj;
	}
	
	/**
	 * @param cls
	 * @return
	 */
	private Object createObjectByField(Class <?> cls) {
		
		Object obj = null;
	
		try 
		{
			obj = cls.newInstance();
			Field [] fields = cls.getDeclaredFields();
			for (Field f : fields) 
			{
				BeanFactory factory = f.getAnnotation(BeanFactory.class);
				if (factory != null) 
				{
					Object myObject = null;
					Class<?> myclass = factory.DIClass();
					if (myclass == null) continue;
			    	if (this.checkByField(myclass))
					    myObject = createObject(myclass);
			    	else
			    		myObject = myclass.newInstance();
			    	
			    	if (myObject != null) 
			    	{						 
			    		f.setAccessible(true);
			    		f.set(obj, myObject);
					}
				}
			}
		} 
		catch (Exception e) 
		{
			System.out.println("BeanFactory �����������:"+e.getMessage());
			e.printStackTrace();
		} 
       
		return obj;
	}
	
	/**
	 * @param cls
     */
    private boolean check(Class<?> cls) {
    	Method []methods = cls.getDeclaredMethods();
		for (Method m : methods) {
			BeanFactory factory = m.getAnnotation(BeanFactory.class);
			if (factory != null) return true;
		}
		return false;
    }
    
	/**
	 * @param cls
     */
    private boolean checkByField(Class<?> cls) {
    	Field []fields = cls.getDeclaredFields();
		for (Field f : fields) {
			BeanFactory factory = f.getAnnotation(BeanFactory.class);
			if (factory != null) return true;
		}
		return false;
    }
   
   
}
